/**
 * 
 */
package uniandes.vista;

import java.io.IOException;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;

import uniandes.mundo.Bunny;

import com.sun.opengl.cg.CGcontext;
import com.sun.opengl.cg.CGparameter;
import com.sun.opengl.cg.CGprogram;
import com.sun.opengl.cg.CgGL;

/**
 * @author Manotas
 * 
 */
public class ControladorEscena3D implements GLEventListener 
{
	// -----------------------------------------------------------------
	// Atributos
	// -----------------------------------------------------------------

	private GLU glu = new GLU();
	private static CGcontext contexto = null;
	private static CGprogram programa = null;
	private static CGparameter cg_Kd = null;
	private static CGparameter cg_ModelViewProj = null;
	private static CGparameter cg_IN_testColor = null;
	private static/* CGprofile */int perfil;

	private int bunnydl;

	// -----------------------------------------------------------------
	// Constructores
	// -----------------------------------------------------------------

	public ControladorEscena3D() 
	{
		//perfil = CgGL.CG_PROFILE_VP20;
	}

	// -----------------------------------------------------------------
	// Metodos Heredados de GLEventListener
	// -----------------------------------------------------------------

	public void display(GLAutoDrawable dibujable) {
		GL gl = dibujable.getGL();
		gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
		dibujarObjetos(gl);
	}

	public void init(GLAutoDrawable dibujable) 
	{
		// Inicializar Cg despues de tener el context activo

		// Creacion de contexto
//		contexto = CgGL.cgCreateContext();
//		revisarErrorCg();

		// Adicion de fuentes al conetxto
//		try {
//			programa = CgGL.cgCreateProgramFromStream(contexto, CgGL.CG_SOURCE,
//					getClass().getClassLoader().getResourceAsStream(
//							"cg/Escena3D.cg"), perfil, null, null);
//		} catch (IOException e) {
//			throw new RuntimeException("Error cargando programa Cg ", e);
//		}
//		revisarErrorCg();

//		System.err.println("LAST LISTING----" + CgGL.cgGetLastListing(contexto)
//				+ "----\n");

//		System.err.println("---- PROGRAM BEGIN ----\n"
//				+ CgGL.cgGetProgramString(programa, CgGL.CG_COMPILED_PROGRAM)
//				+ "---- PROGRAM END ----\n");

		if (programa != null) 
		{
//			CgGL.cgGLLoadProgram(programa);
//			revisarErrorCg();
//
//			cg_Kd = CgGL.cgGetNamedParameter(programa, "Kd");
//			revisarErrorCg();
//
//			cg_ModelViewProj = CgGL.cgGetNamedParameter(programa,
//					"ModelViewProj");
//			revisarErrorCg();
//
//			cg_IN_testColor = CgGL
//					.cgGetNamedParameter(programa, "IN.testColor");
//			revisarErrorCg();
		}

		GL gl = dibujable.getGL();

		// Usar buffer de profundida
		gl.glEnable(GL.GL_DEPTH_TEST);

		// Definicion del tipo de vista
		gl.glMatrixMode(GL.GL_PROJECTION);
		glu.gluPerspective( /* angulo de vision en grados */40.0f,
		/* aspect ratio */1.0f,
		/* Plano Z cercano */1.0f, /* Plano Z lejano */10.0f);
		gl.glMatrixMode(GL.GL_MODELVIEW);
		glu.gluLookAt(0.0f, 0.0f, 5.0f, /* vista en (0,0,5) */
		0.0f, 0.0f, 0.0f, /* centro (0,0,0) */
		0.0f, 1.0f, 0.0f); /* Y es la direccion hacia arriba */
	}

	public void displayChanged(GLAutoDrawable dibujable, boolean modoCambiado,
			boolean dispositivoCambiado) {
	}

	public void reshape(GLAutoDrawable dibujable, int x, int y, int ancho,
			int alto) {
	}

	// -----------------------------------------------------------------
	// Metodos
	// -----------------------------------------------------------------

	private void dibujarObjetos(GL gl) 
	{
		int p, i;

		/*
		 * Inicializa varios parametros de tipo uniform, incluyendo
		 * ModelViewProjection, la cual se usa para transformar la posicion de
		 * entrada en HPOS
		 */

//		if (cg_Kd != null)
//			CgGL.cgGLSetParameter4f(cg_Kd, 1.0f, 1.0f, 1.0f, 45);
//
//		/* Concatene las matrices de proyeccion y del modelo */
//		if (cg_ModelViewProj != null)
//			CgGL.cgGLSetStateMatrixParameter(cg_ModelViewProj,
//					CgGL.CG_GL_MODELVIEW_PROJECTION_MATRIX,
//					CgGL.CG_GL_MATRIX_IDENTITY);
//
//		CgGL.cgGLEnableProfile(perfil);
//
//		CgGL.cgGLBindProgram(programa);
//		revisarErrorCg();

		try {
			bunnydl = Bunny.gen3DObjectList(gl);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}

		gl.glCallList(bunnydl);

//		// CgGL.cgGLUnbindProgram(profile);
//		CgGL.cgGLDisableProfile(perfil);

		gl.glDisable(GL.GL_VERTEX_PROGRAM_ARB);

		gl.glMatrixMode(GL.GL_MODELVIEW);
		gl.glPopMatrix();
	}

	private static void revisarErrorCg() 
	{
		/* CGerror */int error = CgGL.cgGetError();

		if (error != CgGL.CG_NO_ERROR) {
			System.out.println("Error de CG: " + CgGL.cgGetErrorString(error));
			System.exit(1);
		}
	}
}